package com.trytech.mongoocrawler.server.transport.http;

import com.alibaba.fastjson.JSON;

import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLConnection;
import java.util.Iterator;
import java.util.Map;

/**
 * Http客户端
 */
public class HttpClient {
    private String userAgent;//用户代理
    private String proxy;//代理IP
    private String accept;//接收的编码
    public HttpClient setUserAgent(String userAgent){
        this.userAgent = userAgent;
        return this;
    }
    private static class Builder{
        private CrawlerHttpRequest request;
        private String userAgent;
        private String proxy;
        private HttpRequestHeader requestHeader;
        private Map<String,Object> parameterMap;

        private HttpProtocol.METHOD method = HttpProtocol.METHOD.GET;
        public Builder(CrawlerHttpRequest request){
            this.request = request;
        }
        public Builder userAgent(String userAgent){
            this.userAgent = userAgent;
            return this;
        }
        public Builder proxy(String proxy){
            this.proxy = proxy;
            return this;
        }

        public HttpProtocol.METHOD getMethod() {
            return method;
        }

        public Builder setMethod(HttpProtocol.METHOD method) {
            this.method = method;
            return this;
        }

        public HttpRequestHeader getRequestHeader() {
            return requestHeader;
        }

        public Builder setRequestHeader(HttpRequestHeader requestHeader) {
            this.requestHeader = requestHeader;
            return this;
        }

        private URLConnection getConnection(CrawlerHttpRequest request, String method) throws IOException {
            if(request == null)return null;
            HttpRequestProtocol protocol = HttpRequestProtocol.newInstance().setMethod(method).setHeader(requestHeader).setUrl(request.getUrl());
            URLConnection conn  = protocol.getConnection(request);
            return conn;
        }

        public URLConnection build() throws IOException {
            HttpClient client = new HttpClient();
            URLConnection conn = null;
            if(method.equals(HttpProtocol.METHOD.GET)){
                conn  = getConnection(request,HttpProtocol.METHOD.GET.value());
            }else{
                conn  = getConnection(request,HttpProtocol.METHOD.POST.value());
            }
            return conn;
        }
    }


    public static WebResult<HttpResponseProtocol> doGet(CrawlerHttpRequest request){
        try {
            URLConnection conn = new Builder(request)
                                .setMethod(HttpProtocol.METHOD.GET)
                                .build();
            HttpResponseProtocol protocol = HttpResponseProtocol.parse(request, conn);
            return WebResult.newSuccessResult(WebResult.StatusCode.SUCCESS,protocol);
        } catch (IOException e) {
            return null;
        }
    }
    public static WebResult<HttpResponseProtocol> doGet(CrawlerHttpRequest request, HttpRequestHeader requestHeader){
        try {
            URLConnection conn = new Builder(request)
                                .setMethod(HttpProtocol.METHOD.GET)
                                .setRequestHeader(requestHeader)
                                .build();
            HttpResponseProtocol protocol = HttpResponseProtocol.parse(request,conn);
            return WebResult.newSuccessResult(WebResult.StatusCode.SUCCESS,protocol);
        } catch (IOException e) {
            return null;
        }
    }
    public static WebResult<String> doHtmlGet(CrawlerHttpRequest request){
        WebResult<HttpResponseProtocol> result = doGet(request);
        return WebResult.newSuccessResult(WebResult.StatusCode.SUCCESS,result.getData().getBody().getContentString());
    }

    public static WebResult<String> doJSONGet(CrawlerHttpRequest request){
        WebResult<HttpResponseProtocol> result = doGet(request);
        return WebResult.newSuccessResult(WebResult.StatusCode.SUCCESS,result.getData().getBody().toJSON().toJSONString());
    }
    public static HttpBody doPost(CrawlerHttpRequest request){
        PrintWriter writer = null;
        try {
            URLConnection conn = new Builder(request)
                    .setMethod(HttpProtocol.METHOD.POST)
                    .build();
            writer = new PrintWriter(conn.getOutputStream());
            StringBuffer sbf = new StringBuffer();
            Iterator ite = request.getParams().keySet().iterator();
            while (ite.hasNext()){
                String key = (String)ite.next();
                sbf.append(key+"="+ request.getParams().get(key));
                if(ite.hasNext()){
                    sbf.append("&");
                }
            }
            writer.write(sbf.toString());
            writer.flush();
            HttpBody body = HttpResponseProtocol.parse(request,conn).getBody();
            return body;
        } catch (IOException e) {
            return null;
        }
        finally {
            writer.close();
        }
    }

    public static HttpBody doPost(CrawlerHttpRequest request, HttpRequestHeader requestHeader){
        PrintWriter writer = null;
        try {
            URLConnection conn = new Builder(request)
                    .setMethod(HttpProtocol.METHOD.POST)
                    .setRequestHeader(requestHeader)
                    .build();
            writer = new PrintWriter(conn.getOutputStream());
            StringBuffer sbf = new StringBuffer();
            Iterator ite = request.getParams().keySet().iterator();
            while (ite.hasNext()){
                String key = (String)ite.next();
                sbf.append(key+"="+ request.getParams().get(key));
                if(ite.hasNext()){
                    sbf.append("&");
                }
            }
            writer.write(sbf.toString());
            writer.flush();
            HttpBody body = HttpResponseProtocol.parse(request,conn).getBody();
            return body;
        } catch (IOException e) {
            return null;
        }
        finally {
            writer.close();
        }
    }

    public static String doHtmlPost(CrawlerHttpRequest request){
        HttpBody body = doPost(request);
        return body.toString();
    }

    public static JSON doJSONPost(CrawlerHttpRequest request){
        HttpBody body = doPost(request);
        return body.toJSON();
    }
}
